package org.hrqing.chess.dao;

import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.hrqing.chess.entity.Log;
import org.hrqing.chess.entity.LogPiece;
import org.hrqing.chess.util.ClassUtils;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.ZoneOffset;
import java.util.*;

/**
 * @author Hrqing
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LogPieceDao {

    public static class LogPieceRowMapper implements RowMapper<LogPiece> {

        @Override
        public LogPiece mapRow(ResultSet rs, int rowNum) throws SQLException {
            try {
                return ClassUtils.resultSet(rs, LogPiece.class);
            }catch (Exception e) {
                log.error("LogPieceRowMapper error", e);
            }
            return new LogPiece();
        }
    }

    private final NamedParameterJdbcTemplate template;

    public Optional<LogPiece> findById(String id) {
        String sql = """
                select
                id,
                color,
                purpose,
                sign,
                x,
                y,
                log_id as logId
                from t_log_piece
                where id = :id
                """;
        try {
            LogPiece result = template.queryForObject(sql, Map.of("id", id), new LogPieceRowMapper());
            return result.isNew() ? Optional.empty() : Optional.of(result);
        }catch (EmptyResultDataAccessException e) {
            return Optional.empty();
        }

    }

    public List<LogPiece> findByLogId(String id) {
        String sql = """
                select
                id,
                color,
                purpose,
                sign,
                x,
                y,
                log_id as logId
                from t_log_piece
                where log_id = :logId
                """;
        return template.query(sql, Map.of("logId", id), new LogPieceRowMapper());
    }

    public void save(LogPiece log) {
        String selectSql = """
                select count(id) as count
                from t_log_piece
                where id = :id
                """;
        String insertSql = """
                insert into t_log_piece
                (id, color, purpose, sign, x, y, log_id)
                values
                (:id, :color, :purpose, :sign, :x, :y, :logId)
                """;
        String updateSql = """
                update t_log_piece
                set color = :color, purpose = :purpose, sign = :sign,
                x = :x, y = :y,
                log_id = :logId
                where id = :id
                """;
        Map<String, Object> params = new HashMap<>();
        params.put("id", log.getId());
        params.put("color", log.getColor() == null ? null : log.getColor().name());
        params.put("purpose", log.getPurpose() == null ? null : log.getPurpose().name());
        params.put("sign", log.getSign());
        params.put("x", log.getX());
        params.put("y", log.getY());
        params.put("logId", log.getLogId());
        boolean update = false;
        if (log.getId() != null) {
            Boolean exists = template.queryForObject(selectSql, Map.of("id", log.getId()), (rs, rowNum) -> {
                long count = rs.getLong("count");
                return count > 0L;
            });
            if (exists) {
                update = true;
            }
        }
        if (update) {
            template.update(updateSql, params);
        }else {
            template.update(insertSql, params);
        }
    }

    public void delete(String id) {
        if (id == null || id.trim().isEmpty()) {
            return;
        }
        String sql = """
                delete from t_log_piece where id = :id
                """;
        template.update(sql, Map.of("id", id));
    }

    public void deleteAll(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        Map<String, Object> params = new HashMap<>();
        List<String> subjects = new ArrayList<>();
        for (int i = 0; i < ids.size(); i++) {
            String id = "id" + i;
            subjects.add("id=:" + id);
            params.put(id, ids.get(i));
        }
        String sql = """
                delete from t_log_piece where
                """ + String.join(" or ", subjects);
        template.update(sql, params);
    }
}
